<?php


require_once 'Objects/Token.php';


/**
 * Makes Token objects.
 * @author DePhille
 *
 */
class TokenFactory {
	/**
	 * Makes a single token object from the given database row.
	 * 
	 * @param databaseRow An asociative array representing a database row.
	 * @return A newly made Token object.
	 */
	public function fromRow($databaseRow) {
		// Check input:
		if (!is_array($databaseRow) or !$databaseRow["tokenString"]) {
			return NULL;
		}
		
		// Create the token object:
		$token = new Token();
		$token->setTokenString($databaseRow["tokenString"]);
		
		// Fill in the IP Address:
		if (isset($databaseRow["ipAddress"])) {
			$token->setIPAddress($databaseRow["ipAddress"]);
		}
		
		// Fill in the firstLogin:
		if (isset($databaseRow["firstLogin"])) {
			$token->setFirstLogin($databaseRow["firstLogin"]);
		}
		
		// Fill in the lastLogin:
		if (isset($databaseRow["lastLogin"])) {
			$token->setLastLogin($databaseRow["lastLogin"]);
		}
		
		// Fill in the userID:
		if (isset($databaseRow["userID"])) {
			$token->setUserID($databaseRow["userID"]);
		}
		
		// Return the token object:
		return $token;
	}
	
	
	/**
	 * Automatically generates a new unique token for the given user and IP address.
	 * 
	 * @param user		The user to create a token for.
	 * @param ipAddress	IP Address of the user.
	 * @return A newly generated token.
	 */
	public function generate(User $user, $ipAddress) {
		// Try generating a new token:
		Logger::log("TokenFactory", "Generating a new token.");
		$tokenString = $this->makeTokenString();
		$tries = 1;
		while (($tries <= 100) && (TokenTable::getByString($tokenString))) {
			// Token exists, generate new string:
			$tokenString = $this->makeTokenString();
			$tries++;
		}
		
		// Are we out of tries?
		if ($tries > 100) {
			throw new PCException("Unable to generate token after 100 tries.", 500);
		}
		Logger::log("TokenFactory", "Token generated after " . $tries . " tries.");
		
		// Make token Object:
		$token = new Token();
		$token->setUser($user);
		$token->setIPAddress($ipAddress);
		$token->setFirstLogin(time());
		$token->setLastLogin(time());
		$token->setTokenString($tokenString);
		
		// Store token object:
		TokenTable::insert($token);
		
		// Return token:
		return $token;		
	}
	
	
	/**
	 * Private method. Simply creates a random 128 character token string.
	 * 
	 * @return A random 128 character tokenString.
	 */
	private function makeTokenString() {
		$token = "";
		for($i=0; $i<128; $i++) {
			$token .= chr(rand(33, 126));
		}
		return $token;
	}
	

}
?>
